/*
 * Copyright (c) 2005, The haXe Project Contributors
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package js;

// allow both indexed and dot accessses
extern class HtmlCollection<T> implements ArrayAccess<T>, implements Dynamic<T> {
	public var length(default,null) : Int;
}

// the base typedef for every DOM element
interface MetaDom<T> {
	public var nodeName : String;
	public var nodeType : Int;
	public var nodeValue : String;

	public var parentNode : T;
	public var childNodes : HtmlCollection<T>;
	public var firstChild : T;
	public var lastChild : T;
	public var nextSibling : T;
	public var previousSibling : T;

	public function appendChild( child : T ) : Void;
	public function cloneNode( deep : Bool ) : T;
	public function hasChildNodes() : Bool;
	public function insertBefore( newChild : T, refChild : T ) : Void;
	public function removeChild( child : T ) : T;
	public function replaceChild( child : T, oldChild : T ) : Void;
	public function getAttribute( attr : String ) : String;
	public function setAttribute( attr : String, val : String ) : Void;
}

typedef Dom = MetaDom<Dom>

typedef HtmlDom = {> MetaDom<HtmlDom>,
	public var id : String;
	public var title : String;
	public var lang : String;
	public var dir : String;
	public var innerHTML : String;
	public var className : String;

	public var style : Style;

	public function getElementsByTagName( tag : String ) : HtmlCollection<HtmlDom>;

	public var scrollTop : Int;
	public var scrollLeft : Int;
	public var scrollHeight(default,null) : Int;
	public var scrollWidth(default,null) : Int;
	public var clientHeight(default,null) : Int;
	public var clientWidth(default,null) : Int;
	public var offsetParent : HtmlDom;
	public var offsetLeft : Int;
	public var offsetTop : Int;
	public var offsetWidth : Int;
	public var offsetHeight : Int;

	public function blur() : Void;
	public function click() : Void;
	public function focus() : Void;

	public var onscroll : Event -> Void;
	public var onblur : Event -> Void;
	public var onclick : Event -> Void;
	public var ondblclick : Event -> Void;
	public var onfocus : Event -> Void;
	public var onkeydown : Event -> Void;
	public var onkeypress : Event -> Void;
	public var onkeyup : Event -> Void;
	public var onmousedown : Event -> Void;
	public var onmousemove : Event -> Void;
	public var onmouseout : Event -> Void;
	public var onmouseover : Event -> Void;
	public var onmouseup : Event -> Void;
	public var onresize : Event -> Void;
}

typedef FormElement = {> HtmlDom,

	public var disabled : Bool;
	public var form : Form;
	public var name : String;
	public var type : String;
	public var value : String;

	public function select() : Void;
	public var onselect : Event -> Void;
	public var onchange : Event -> Void;
}

typedef Anchor = {> HtmlDom,

	public var accessKey : String;
	public var href : String;
	public var name: String;
	public var rel : String;
	public var rev : String;
	public var tabIndex : Int;
	public var target : String;

#if ie5
	public var charset : String;
	public var coords : String;
	public var hreflang : String;
	public var shape : String;
	public var type : String;
#end

}

typedef Body = {> HtmlDom,
	// IE only, NO W3C public var accessKey : String;
	public var aLink : String;
	public var background : String;
	public var bgColor : String;
	public var link : String;
	public var text : String;
	public var vLink : String;
}

typedef Button = {> FormElement,
}

typedef Checkbox = {> FormElement,
	public var checked : Bool;
	public var defaultChecked : Bool;
}

typedef Document = {> HtmlDom,
	public var anchors : HtmlCollection<Anchor>;
	// applets : Applet is deprecated in Dom2
	public var forms : HtmlCollection<Form>;
	public var images : HtmlCollection<Image>;
	public var links : HtmlCollection<Link>;
	// plugins : Not in IE, not in W3C

	/* deprecated in Dom2 , use body
	public var alinkColor;
	public var background;
	public var bgColor;
	public var fgColor;
	public var linkColor;
	public var vlinkColor;
	*/

	public var body : Body;
	public var cookie : String;
	public var domain : String;
	public var referrer : String;

	// TODO : public var URL : String;

	// not W3C , need infos : public var embeds : HtmlCollection<Embed>;
	// public var lastModified : Date; // commented : does not include date by default
	public var styleSheets : HtmlCollection<StyleSheet>;
	public function getElementsByTag( tag : String ) : HtmlCollection<HtmlDom>;

	public function open() : Void;
	public function write( str : String ) : Void;
	public function writeln( str : String ) : Void;
	public function close() : Void;
	public function getElementById( id : String ) : HtmlDom;
	public function getElementsByName( name : String ) : HtmlCollection<HtmlDom>;
	public function createElement( name : String ) : HtmlDom;
	public function createTextNode( text : String ) : HtmlDom;
}

typedef Event = {
	public var target : HtmlDom;
	public var type : String;

	// TO COMPLETE... (need infos)
	public var clientX : Int;
	public var clientY : Int;
	public var screenX : Int;
	public var screenY : Int;
	public var button : Int;
	public var keyCode : Int;
	public var shiftKey : Bool;
	public var ctrlKey : Bool;
	public var altKey : Bool;
	public var cancelBubble : Bool;
}

typedef FileUpload = {> FormElement,
	public var defaultValue : String;
}

typedef Form = {> HtmlDom,

	public var elements : HtmlCollection<FormElement>;

	public var acceptCharset : String;
	public var action : String;
	public var encoding : String;
	public var enctype : String;
	public var length : Int;
	public var method : String;
	public var name : String;
	public var tabIndex : Int;
	public var target : String;

	public function reset() : Void;
	public function submit() : Void;

	public var onreset : Event -> Void;
	public var onsubmit : Event -> Bool;
}

typedef Frame = {> HtmlDom,

	public var contentDocument : Document;
	public var frameBorder : String;
	// IE6 only ? public var longDesc : String
	public var marginHeight : String;
	public var marginWidth : String;
	public var name : String;
	public var noResize : Bool;
	public var scrolling : String;
	public var src : String;
}

typedef Frameset = {> HtmlDom,
	public var cols : Int;
	public var rows : Int;
}

typedef Hidden = {> FormElement,
	public var defaultValue : String;
}

typedef History = {
	public var length : Int;
	public function back() : Void;
	public function forward() : Void;
	public function go( p : Dynamic ) : Void;
}

typedef IFrame = {> HtmlDom,
	public var contentWindow : Window;
	public var frameBorder : String;
	public var height : Int;
	public var width : Int;
	// IE6 only ? public var longDesc : String
	public var marginHeight : String;
	public var marginWidth : String;
	public var name : String;
	public var scrolling : String;
	public var src : String;
}

typedef Image = {> HtmlDom,
	public var align : String;
	public var alt : String;
	public var border : String;
	public var height : Int;
	public var hspace : Int;
	public var isMap : Bool;
	// IE only : public var longDesc : String;
	public var name : String;
	public var src : String;
	public var useMap : String;
	public var vspace : Int;
	public var width : Int;

	public var complete : Bool;
	public var lowsrc : String;

	public var onabort : Event -> Void;
	public var onerror : Event -> Void;
	public var onload : Event -> Void;
}

typedef Link = {> HtmlDom,
	public var charset : String;
	public var disabled : Bool;
	public var href : String;
	public var hreflang : String;
	public var media : String;
	public var rel : String;
	public var rev : String;
	public var target : String;
	public var type : String;
	public var name : String;
	public var onload : Event -> Void;
}

typedef Location = {
	public var hash : String;
	public var host : String;
	public var hostname : String;
	public var href : String;
	public var pathname : String;
	public var port : Int;
	public var protocol : String;
	public var search : String;

	public function assign( url : String ) : Void;
	public function reload( ?forceReload : Bool ) : Void;
	public function replace( url : String ) : Void;
}

typedef Navigator = {
	// public var plugins : HtmlCollection<???>

	public var appCodeName : String;
	public var appName : String;
	public var appVersion : String;
	public var cookieEnabled : Bool;
	public var platform : String;
	public var userAgent : String;

	/* IE only ?
	public var appMinorVersion : String
	public var browserLanguage : String
	public var cpuClass : String;
	public var onLine : Bool;
	public var systemLanguage : String;
	public var userLanguage : String;
	*/

	public function javaEnabled() : Bool;
	public function taintEnabled() : Bool;
}

typedef Option = {> FormElement,
	public var defaultSelected : Bool;
	public var selected : Bool;
	public var text : String;
}

typedef Password = {> FormElement,
	public var defaultValue : String;
	public var maxLength : Int;
	public var readOnly : Bool;
	public var size : Int;
}

typedef Radio = {> FormElement,
	public var checked : Bool;
	public var defaultChecked : Bool;
	public var size : Int;
}

typedef Reset = {> FormElement,
}

typedef Screen = {
	public var availHeight : Int;
	public var availWidth : Int;
	public var colorDepth : Int;
	public var height : Int;
	public var width : Int;

	// FF only ? public var pixelDepth : Int;

	/* IE only ?
	public var bufferDepth : Int;
	public var deviceXDPI : Int;
	public var deviceYDPI : Int;
	public var logicalXDPI : Int;
	public var logicalYDPI : Int;
	public var updateInterval : Int;
	*/
}

typedef Select = {> FormElement,
	public var options : HtmlCollection<Option>;
	public var length : Int;
	public var multiple : Bool;
	public var selectedIndex : Int;
	public var size : Int;

	public function remove( o : Int ) : Void;
}

typedef Style = {
	// Position
	public var left : String;
	public var bottom : String;
	public var height : String;
	public var width : String;
	public var top : String;
	public var right : String;
	public var zIndex : Int;
	public var position : Dynamic;

	// BG
	public var background : Dynamic;
	public var backgroundAttachment : Dynamic;
	public var backgroundColor : Dynamic;
	public var backgroundImage : Dynamic;
	public var backgroundPosition : Dynamic;
	public var backgroundRepeat : Dynamic;

	// Border
	public var border : Dynamic;
	public var borderBottom : Dynamic;
	public var borderLeft : Dynamic;
	public var borderRight : Dynamic;
	public var borderTop : Dynamic;
	public var borderBottomColor : Dynamic;
	public var borderLeftColor : Dynamic;
	public var borderRightColor : Dynamic;
	public var borderTopColor : Dynamic;
	public var borderBottomStyle : Dynamic;
	public var borderLeftStyle : Dynamic;
	public var borderRightStyle : Dynamic;
	public var borderTopStyle : Dynamic;
	public var borderBottomWidth : Dynamic;
	public var borderLeftWidth : Dynamic;
	public var borderRightWidth : Dynamic;
	public var borderTopWidth : Dynamic;
	public var borderColor : Dynamic;
	public var borderStyle : String;
	public var borderWidth : Dynamic;


	public var margin : Dynamic;
	public var marginBottom : Dynamic;
	public var marginLeft : Dynamic;
	public var marginRight : Dynamic;
	public var marginTop : Dynamic;

	public var outline : Dynamic;
	public var outlineColor : Dynamic;
	public var outlineStyle : Dynamic;
	public var outlineWidth : Dynamic;
	public var padding : Dynamic;
	public var paddingBottom : Dynamic;
	public var paddingLeft : Dynamic;
	public var paddingRight : Dynamic;
	public var paddingTop : Dynamic;

	public var clear : String;
	public var clip : Dynamic;
	public var clipBottom : Dynamic;
	public var clipLeft : Dynamic;
	public var clipRight : Dynamic;
	public var clipTop : Dynamic;

	public var content : Dynamic;
	public var counterIncrement : Dynamic;
	public var counterReset : Dynamic;
	public var cssFloat : Dynamic;
	public var cursor : Dynamic;
	public var direction : Dynamic;
	public var display : Dynamic;

	public var markerOffset : Dynamic;
	public var marks : Dynamic;
	public var maxHeight : Dynamic;
	public var maxWidth : Dynamic;
	public var minHeight : Dynamic;
	public var minWidth : Dynamic;
	public var overflow : Dynamic;
	public var overflowX : Dynamic;
	public var overflowY : Dynamic;
	public var styleFloat : Dynamic;
	public var verticalAlign : Dynamic;
	public var visibility : Dynamic;
	public var zoom : Dynamic;

	public var listStyle : Dynamic;
	public var listStyleImage : Dynamic;
	public var listStylePosition : Dynamic;
	public var listStyleType : String;

	public var cssText : Dynamic;

	public var color : Dynamic;
	public var font : Dynamic;
	public var fontFamily : Dynamic;
	public var fontSize : Dynamic;
	public var fontSizeAdjust : Dynamic;
	public var fontStretch : Dynamic;
	public var fontStyle : Dynamic;
	public var fontVariant : Dynamic;
	public var fontWeight : Dynamic;
	public var letterSpacing : Dynamic;
	public var lineBreak : Dynamic;
	public var lineHeight : Dynamic;
	public var quotes : Dynamic;
	public var rubyAlign : Dynamic;
	public var rubyOverhang : Dynamic;
	public var rubyPosition : Dynamic;
	public var textAlign : Dynamic;
	public var textAlignLast : Dynamic;
	public var textAutospace : Dynamic;
	public var textDecoration : Dynamic;
	public var textDecorationBlink : Dynamic;
	public var textDecorationLineThrough : Dynamic;
	public var textDecorationLineNone : Dynamic;
	public var textDecorationLineOverline : Dynamic;
	public var textDecorationLineUnderline : Dynamic;
	public var textIndent : Dynamic;
	public var textJustify : Dynamic;
	public var textJustifyTrim : Dynamic;
	public var textKashidaSpace : Dynamic;
	public var textOverflow : Dynamic;
	public var textShadow : Dynamic;
	public var textTransform : Dynamic;
	public var textUnderlinePosition : Dynamic;
	public var unicodeBidi : Dynamic;
	public var whiteSpace : Dynamic;
	public var wordBreak : Dynamic;
	public var wordSpacing : Dynamic;
	public var wordWrap : Dynamic;
	public var writingMode : Dynamic;
}

typedef StyleSheet = {
	public var type : String;
	public var disabled : Bool;
	public var href : String;
	public var title : String;
	// ??? more ???
}

typedef Submit = {> FormElement,
	public var onselectstart : Event -> Void;
}

typedef Text = {> FormElement,
	public var defaultValue : String;
	public var maxLength : Int;
	public var readOnly : Bool;
	public var size : Int;
}

typedef Textarea = {> FormElement,
	public var cols : Int;
	public var rows : Int;
	public var defaultValue : String;
	public var readOnly : Bool;
}

extern class Window implements Dynamic{

	public var history : History;
	public var location : Location;
	public var document : Document;
	public var navigator : Navigator;
	public var screen : Screen;

	public var frames : HtmlCollection<Frame>;
	public var closed : Bool;
	public var defaultStatus : String;
	public var length : Int;
	public var name : String;
	public var opener : Window;
	public var parent : Window;

	
	public var self : Window;
	public var status : String;
	public var top : Window;
	//custom extensions
	public var session:Hash<String>;
	public var xContent:Xml;

	public function alert( msg : String ) : Void;
	public function blur() : Void;
	// clearInterval
	// clearTimeout
	public function close() : Void;
	public function confirm( msg : String ) : Bool;
	public function focus() : Void;
	public function moveBy( dx : Int, dy : Int ) : Void;
	public function moveTo( x : Int, y : Int ) : Void;
	public function print() : Void;
	public function prompt( msg : String, ?def : String ) : String;
	// FF1.5 resizeTo
	public function scrollBy( dx : Int, dy : Int ) : Void;
	public function scrollTo( x : Int, y : Int ) : Void;
	public function open( url : String, ?name : String, ?features : String ) : Window;
	// setInterval
	// setTimeout

	public var innerWidth : Int;
	public var innerHeight : Int;
	public var outerWidth : Int;
	public var outerHeight : Int;

	/* IE only ?
	clientInformation
	clipboardData
	event
	external
	dialogArguments
	dialog....
	frameElement
	offscreenBuffering
	returnValue
	screenTop
	createPopup()
	execScript()
	navigate(url)
	resizeBy()
	scroll();
	setActive()
	showHelp()
	show...()
	*/

 	// events
	public var onload : Event -> Void;
	public var onresize : Event -> Void;
	public var onscroll : Event -> Void;
	public var onunload : Event -> Void;
	public var onerror : Event -> Void;

}
